﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Core;
using Microsoft.Office.Interop.Outlook;
using System.Windows.Forms;
using System.Threading;

namespace EncryptNotesAddIn
{
    public partial class ThisAddIn
    {
        private const string START_ENCRYPTED_TEXT= "<START_ENCRYPTED_TEXT>";
        private const string END_ENCRYPTED_TEXT = "<END_ENCRYPTED_TEXT>";

        private Outlook.NoteItem currentNote;
        private EnterPasswordForm pwdForm;

        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            this.Application.ItemContextMenuDisplay += new ApplicationEvents_11_ItemContextMenuDisplayEventHandler(Application_ItemContextMenuDisplay);
        }

        void Application_ItemContextMenuDisplay(CommandBar CommandBar, Selection Selection)
        {
            if (Selection.Count > 0)
            {
                currentNote = Selection[1] as Outlook.NoteItem;
                if (currentNote == null) return;

                Office.CommandBarButton encryptButton = CommandBar.Controls.Add(Office.MsoControlType.msoControlButton, missing, 
                    missing, missing, missing) as Office.CommandBarButton;                
                encryptButton.Caption = "Encrypt Note";
                encryptButton.Click += new _CommandBarButtonEvents_ClickEventHandler(encryptButton_Click);

                Office.CommandBarButton decryptButton = CommandBar.Controls.Add(Office.MsoControlType.msoControlButton, missing, 
                    missing, missing, missing) as Office.CommandBarButton;
                decryptButton.Caption = "Decrypt Note";
                decryptButton.Click += new _CommandBarButtonEvents_ClickEventHandler(decryptButton_Click);

            }
                        
        }

        DateTime lastDecryptionAttempt = DateTime.Now;

        void decryptButton_Click(CommandBarButton Ctrl, ref bool CancelDefault)
        {
            if (currentNote == null) return;
            if (pwdForm == null) pwdForm = new EnterPasswordForm();
            pwdForm.ClearPassword();

            if (DateTime.Now.Subtract(lastDecryptionAttempt).TotalSeconds < 3) Thread.Sleep(5000);

            pwdForm.ShowDialog();
            if (pwdForm.Password == string.Empty) return;

            string noteText = currentNote.Body;
            string noteSubject = currentNote.Subject;

            string encryptedString = UnwrapEncryptedText(noteText);
            string decryptedString = Encryption.DecryptData(encryptedString, pwdForm.Password);

            currentNote.Body = decryptedString;
            currentNote.Save();

            lastDecryptionAttempt = DateTime.Now;

        }

        void encryptButton_Click(CommandBarButton Ctrl, ref bool CancelDefault)
        {
            if (currentNote == null) return;
            if (pwdForm == null) pwdForm = new EnterPasswordForm();
            pwdForm.ClearPassword();
            pwdForm.ShowDialog();
            if (pwdForm.Password == string.Empty) return;

            string noteText = currentNote.Body;
            string noteSubject = currentNote.Subject;
                        
            string encryptedText = Encryption.EncryptData(noteText, pwdForm.Password);
            string newNoteText = WrapEncryptedText(encryptedText, noteSubject);

            currentNote.Body = newNoteText;
            currentNote.Save();


        }

        

        private string UnwrapEncryptedText(string text)
        {
            if (!text.Contains(START_ENCRYPTED_TEXT)) return string.Empty;
            string[] lines = text.Split('\n');
            StringBuilder encryptedLines = new StringBuilder();
            bool startFound = false;
            foreach (string line in lines)
            {
                if (line.StartsWith(END_ENCRYPTED_TEXT)) break;                    

                if (startFound)
                {
                    encryptedLines.Append(line.Replace("\r",""));
                }

                if (line.StartsWith(START_ENCRYPTED_TEXT))
                {
                    startFound = true;
                }

                
            }

            return encryptedLines.ToString();
        }

        private string WrapEncryptedText(string encryptedText, string subject)
        {
            StringBuilder newText = new StringBuilder();
            newText.AppendFormat("{0}\n\n{1}\n{2}\n{3}", subject, START_ENCRYPTED_TEXT, encryptedText, END_ENCRYPTED_TEXT);
            return newText.ToString();
        }

        

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
            Encryption.FinishEncryption();
        }

        #region VSTO generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }
        
        #endregion
    }
}
